package org.bjf.modules.process.service;

import static org.bjf.modules.process.constants.ProcessConstant.APPROVED;
import static org.bjf.modules.process.constants.ProcessConstant.AUDITOR_LIST;
import static org.bjf.modules.process.constants.ProcessConstant.BIZ_INFO;
import static org.bjf.modules.process.constants.ProcessConstant.CURRENT_AUDITOR;
import static org.bjf.modules.process.constants.ProcessConstant.HAS_NEXT_AUDITOR;
import static org.bjf.modules.process.constants.ProcessConstant.LEFT_AUDITOR_LIST;
import static org.bjf.modules.process.constants.ProcessConstant.USER_AUDIT_INFO;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.bjf.modules.process.bean.ProcessAudit;
import org.bjf.modules.process.bean.ProcessInfo;
import org.bjf.modules.process.bean.ProcessResultEvent;
import org.bjf.modules.process.bean.UserAuditInfo;
import org.bjf.modules.process.constants.EnumAuditStatus;
import org.bjf.modules.sys.bean.SysUser;
import org.bjf.utils.EventBusUtil;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;

/**
 * @author bjf
 */
@Slf4j
@Component
public class StandardProcessListener {

  @Autowired
  private ProcessAuditService processAuditService;
  @Autowired
  private ProcessInfoService processInfoService;
  @Autowired
  private EventBusUtil eventBusUtil;

  @PostConstruct
  private void init() {
    // 注册事件监听器
    eventBusUtil.register(new ProcessResultListener());
  }
  /**
   * 流程实例启动监听:从审批人列表里面取出第一个作为下一审批人
   */
  public void start(DelegateExecution execution) {
    log.info("进入流程实例启动监听器");

    //====1.从审批人列表里面设置下一个审批人
    String json = (String) execution.getVariable(AUDITOR_LIST);
    List<SysUser> auditors = JSON.parseArray(json, SysUser.class);
    SysUser nextAuditor = auditors.remove(0);
    execution.setVariable(CURRENT_AUDITOR, JSON.toJSONString(nextAuditor));

    //====2.设置剩余审批人
    if (!CollectionUtils.isEmpty(auditors)) {
      execution.setVariable(LEFT_AUDITOR_LIST, JSON.toJSONString(auditors));
    }

  }

  /**
   * 用户审批：设置为当前审批人
   */
  public void initTask(DelegateTask delegateTask) {
    log.info("进入创建审批任务监听器");

    //====1.从流程变量里取出当前审批人设置为任务审批人
    String json = (String) delegateTask.getVariable(CURRENT_AUDITOR);
    SysUser currentAuditor = JSON.parseObject(json, SysUser.class);
    delegateTask.setAssignee(currentAuditor.getSysUserId() + "");
    delegateTask.removeVariable(CURRENT_AUDITOR);

    //====2.记录审批信息
    ProcessAudit obj = new ProcessAudit();
    obj.setPiId(delegateTask.getProcessInstanceId());
    obj.setTaskId(delegateTask.getId());
//    obj.setAuditUserId(loginInfo.getUserId());
    List<SysUser> leftAuditors = this.getLeftAuditors(delegateTask.getVariables());
    if (!leftAuditors.isEmpty()) {
      obj.setNextUserId(leftAuditors.get(0).getSysUserId());
    }
    processAuditService.add(obj);

  }

  /**
   * 完成任务：设置APPROVED通过状态
   */
  public void completeTask(DelegateTask delegateTask) {
    log.info("进入提交任务监听器");

    //====1.取出审批信息
    String json = (String) delegateTask.getVariable(USER_AUDIT_INFO);
    UserAuditInfo userAuditInfo = JSON.parseObject(json, UserAuditInfo.class);

    if (userAuditInfo != null && userAuditInfo.getAuditStatus() != null && userAuditInfo
        .getAuditStatus().equals(EnumAuditStatus.AGREE.getCode())) {
      //====1.1审批通过
      delegateTask.setVariable(APPROVED, Boolean.TRUE);
    } else {
      //====1.2审批拒绝
      delegateTask.setVariable(APPROVED, Boolean.FALSE);
    }

    //====更新审批信息
    ProcessAudit up = new ProcessAudit();
    up.setAuditStatus(userAuditInfo.getAuditStatus());
    up.setAuditComment(userAuditInfo.getAuditComment());
    processAuditService
        .update(up, new LambdaQueryWrapper<ProcessAudit>()
            .eq(ProcessAudit::getTaskId, delegateTask.getId()));
  }

  /**
   * 判断是否有下一个审批人：有，设置下一个审批人
   */
  public void setAuditor(DelegateExecution execution) {
    log.info("进入设置审批人监听器");

    //====1.清除标识
    execution.removeVariable(APPROVED);
    execution.removeVariable(CURRENT_AUDITOR);
    execution.setVariable(HAS_NEXT_AUDITOR, Boolean.FALSE);

    //===2.获取剩余审批人列表
    List<SysUser> leftAuditors = getLeftAuditors(execution.getVariables());
    if (leftAuditors.isEmpty()) {
      log.info("没有下一个审批人");
      return;
    }

    //====3.设置下一个审批人
    execution.setVariable(CURRENT_AUDITOR, JSON.toJSONString(leftAuditors.remove(0)));
    execution.setVariable(HAS_NEXT_AUDITOR, Boolean.TRUE);
    if (!CollectionUtils.isEmpty(leftAuditors)) {
      execution.setVariable(LEFT_AUDITOR_LIST, JSON.toJSONString(leftAuditors));
    } else {
      execution.removeVariable(LEFT_AUDITOR_LIST);
    }
  }

  /**
   * 流程驳回
   */
  public void reject(DelegateExecution execution) {
    log.info("进入流程驳回监听器");

    //====更新流程状态
    ProcessInfo up = new ProcessInfo();
    up.setStatus(EnumAuditStatus.REJECT.getCode());
    processInfoService
        .update(up, new LambdaQueryWrapper<ProcessInfo>()
            .eq(ProcessInfo::getPiId, execution.getProcessInstanceId()));

    //=====发布eventBus事件
    postBusMsg(execution, EnumAuditStatus.REJECT);
  }

  /**
   * 流程通过
   */
  public void agree(DelegateExecution execution) {
    log.info("进入流程通过监听器");
    //====更新流程状态
    ProcessInfo up = new ProcessInfo();
    up.setStatus(EnumAuditStatus.AGREE.getCode());
    processInfoService
        .update(up, new LambdaQueryWrapper<ProcessInfo>().eq(ProcessInfo::getPiId, execution.getProcessInstanceId()));

    //=====发布eventBus事件
    postBusMsg(execution, EnumAuditStatus.AGREE);

  }

  private void postBusMsg(DelegateExecution execution, EnumAuditStatus auditStatus) {
    //=====取出业务信息
    String json = (String) execution.getVariable(BIZ_INFO);
    ProcessInfo processInfo = JSON.parseObject(json, ProcessInfo.class);

    //====发布eventBus事件
    ProcessResultEvent event = new ProcessResultEvent();
    event.setAuditStatus(auditStatus);
    event.setBizType(processInfo.getBizType());
    event.setBizKey(processInfo.getBizKey());
    eventBusUtil.post(event);
    log.info("流程审批结束，发送eventBus消息：{}", JSON.toJSONString(event));
  }

  /**
   * 获取剩余审批人列表
   */
  private List<SysUser> getLeftAuditors(Map<String, Object> vars) {
    Object var = vars.get(LEFT_AUDITOR_LIST);
    if (var == null) {
      return Collections.emptyList();
    }
    String json = (String) var;

    return JSON.parseArray(json, SysUser.class);
  }
}
